package org.nanhill.xsheet.input.excel;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.util.Region;
import org.nanhill.commons.model.table.Cell;
import org.nanhill.commons.model.table.Row;
import org.nanhill.commons.model.table.Table;
import org.nanhill.support.poi.HSSFKit;
import org.nanhill.xsheet.XSheetParseException;
import org.nanhill.xsheet.model.XSheetModel;

/**
 * default input builder for : poi hssf sheet --> xsheet model. not thread safe.
 * 
 * @author alin
 * 
 */
public class DefaultExcelInputBuilder extends ExcelInputBuilder {
	@Override
	protected void initModel() throws XSheetParseException {
		this.model = new XSheetModel();
	}

	@Override
	protected void buildStyle() throws XSheetParseException {
		// TODO Auto-generated method stub

	}

	@Override
	protected void buildTables() throws XSheetParseException {
		for (int i = 0; i < this.workbook.getNumberOfSheets(); i++) {
			HSSFSheet sheet = this.workbook.getSheetAt(i);
			this.buildTable(sheet);
		}

	}

	@Override
	protected void buildTable(HSSFSheet hssfSheet) throws XSheetParseException {
		if (null == hssfSheet)
			return;
		Table table = this.model.createTable();
		for (int i = hssfSheet.getFirstRowNum(); i <= hssfSheet.getLastRowNum(); i++) {
			this.buildRow(hssfSheet.getRow(i), table);
		}
		this.buildMergeCells(hssfSheet, table);
	}

	@Override
	protected void buildRow(HSSFRow hssfRow, Table table)
			throws XSheetParseException {
		if (null == hssfRow)
			return;
		Row row = table.createRow();
		for (int i = hssfRow.getFirstCellNum(); i <= hssfRow.getLastCellNum(); i++) {
			this.buildCell(hssfRow.getCell((short) i), row);
		}

	}

	@Override
	protected void buildCell(HSSFCell hssfCell, Row row)
			throws XSheetParseException {
		if (null == hssfCell)
			return;
		row.createCell(HSSFKit.getValue(hssfCell));
	}

	private void buildMergeCells(HSSFSheet hssfSheet, Table table) {
		for (int i = 0; i < hssfSheet.getNumMergedRegions(); i++) {
			Region region = hssfSheet.getMergedRegionAt(i);
			this.mergeCells(region, table);
		}
	}

	private void mergeCells(Region region, Table table) {
		int rowFrom = region.getRowFrom();
		int rowTo = region.getRowTo();
		short columnFrom = region.getColumnFrom();
		short columnTo = region.getColumnTo();
		Cell mergedCell = table.getRow(rowFrom).getCell(columnFrom);
		mergedCell.setRowspan(rowTo - rowFrom + 1);
		mergedCell.setColspan(columnTo - columnFrom + 1);
		// remove covered cell in same row
		Row row = table.getRow(rowFrom);
		for (int j = columnTo; j > columnFrom; j--) {
			row.setCell(j, null);
		}
		// remove covered cell in other row
		for (int i = rowFrom + 1; i <= rowTo; i++) {
			row = table.getRow(i);
			for (int j = columnTo; j >= columnFrom; j--) {
				row.setCell(j, null);
			}
		}
	}

	public void construct() throws XSheetParseException {
		this.initModel();
		this.buildStyle();
		this.buildTables();
	}

}
